from sqlalchemy import MetaData
from sqlalchemy.schema import CreateColumn,CreateTable

from environment import environment
from core.base_model import Base


def adjust_table():
    environment.initialize()
    # 获取所有的表,需要先加载模型
    # 获取现有表 https://www.pythonheidong.com/blog/article/142463/498dcf6ef86f65247503/
    # 获取现存的模型和存在的表格
    class_tables = Base.metadata.sorted_tables
    engine = environment.engine
    MATA_DATA = MetaData(bind=engine, reflect=True)
    db_tables = MATA_DATA.sorted_tables
    print("类表格", class_tables)
    print("数据库中的表格", db_tables)

    add_columns = [] # 添加的列
    update_columns = [] # 修改类型的列
    no_tables = [] # 没有世界表的类

    # 遍历类模型，找出没有表格的模型，增加的列，变更的类的类型
    db_tables_map = {_i.name:_i for _i in db_tables}

    for _c in class_tables:
        if _c.name not in list(db_tables_map.keys()):
            no_tables.append(_c)
        else:
            # 存在就查找列是否更改或者变更
            db_table = db_tables_map[_c.name.lower()] # 表
            # 遍历表的列,做映射
            db_table_column_map = { 
                _d.name:_d
                for _d in db_table.columns
            }
            # 遍历类的列
            for _cc in _c.columns:
                _cname = _cc.name # 类的列名
                _ctype = str(_cc.type) # 类的列的类型
                _dtype = str(db_table_column_map[_cc.name].type) # 表的列类型
                # 新增列处理
                if _cname not in list(db_table_column_map.keys()):
                    add_columns.append(_cc) 
                elif _ctype != _dtype:
                    # 一般的话我们不允许列类型做较大的改动，有时候只允许改动VARCHAR的长度
                    update_columns.append(_cc)


    # 新增表格
    def handle_no_tabel():
        for no_tabel in no_tables:
            # https://www.osgeo.cn/sqlalchemy/core/metadata.html?highlight=create#sqlalchemy.schema.Table.create
            print(CreateTable(no_tabel)) # 打印出执行的DDL语句
            no_tabel.create(environment.engine)
            # 除了新增表格之外，还会对于不同数据库的表格做一些其他的处理
            #。。。

    handle_no_tabel()

    # 新增列
    def handle_add_columns():
        for add_cloumn in add_columns:
            field = CreateColumn(add_cloumn) # 返回字符串，如 "age VARCHAR(10)"
            _field,_type = field.split(" ")
            # 一般为了兼容处理，我们会监测当前环境的数据库类型，然后拼接sql，这里以mysql为例
            # if is_mysql:
            sql = f"alter table {add_cloumn.table.name} `{_field}` {_type};"
            environment.engine.execute(sql)

    handle_add_columns()
    # 修改列
    def handle_update_columns():
        for update_column in update_columns:
            field = CreateColumn(update_column) # 返回字符串，如 "age VARCHAR(10)" 
            _field,_type = field.split(" ")
            sql = f"alter table {update_column.table.name} modify column `{_field}` {_type};"
            environment.engine.execute(sql)

    handle_update_columns()


if __name__ == "__main__":
    print("start")
    adjust_table()
    print("end")
